home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / progem.lzh / apndx10.prf < prev    next >
Text File  |  1987-06-23  |  15KB  |  568 lines

  1. .!****************************************************************************
  2. .! 
  3. .! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
  4. .!
  5. .! ** Professional GEM ** by Tim Oren
  6. .!
  7. .! Proff File by ST enthusiasts at
  8. .! Case Western Reserve University
  9. .! Cleveland, Ohio
  10. .! uucp : decvax!cwruecmp!bammi
  11. .! csnet: bammi@case
  12. .! arpa : bammi%case@csnet-relay
  13. .! compuserve: 71515,155
  14. .!
  15. .!****************************************************************************
  16. .!
  17. .!            Begin Appendix 10
  18. .!
  19. .!***************************************************************************
  20. .!
  21. .!
  22. .AP X Sample Code for Part XIII
  23. #include "portab.h"                /* portable coding conv    */
  24. #include "machine.h"                /* machine depndnt conv    */
  25. #include "obdefs.h"                /* object definitions    */
  26. #include "gembind.h"                /* gem binding structs    */
  27. #include "taddr.h"
  28.  
  29. #define    M1_ENTER    0x0000
  30. #define    M1_EXIT        0x0001
  31.  
  32. #define BS    0x0008
  33. #define    TAB    0x0009
  34. #define    CR    0x000D
  35. #define ESC    0x001B
  36. #define    BTAB    0x0f00
  37. #define    UP    0x4800
  38. #define    DOWN    0x5000
  39. #define    DEL    0x5300
  40.                     /* Global variables used by */
  41.                     /* 'mapped' functions        */
  42. MLOCAL    GRECT    br_rect;        /* Current break rectangle  */
  43. MLOCAL    WORD    br_mx, br_my, br_togl;    /* Break mouse posn & flag  */ 
  44. MLOCAL    WORD    fn_obj;            /* Found tabable object        */
  45. MLOCAL    WORD    fn_last;        /* Object tabbing from        */
  46. MLOCAL    WORD    fn_prev;        /* Last EDITABLE obj seen   */
  47. MLOCAL    WORD    fn_dir;            /* 1 = TAB, 0 = BACKTAB        */
  48.  
  49. /************* Utility routines for new forms manager ***************/
  50.  
  51.     VOID
  52. objc_toggle(tree, obj)            /* Reverse the SELECT state */
  53.     LONG    tree;            /* of an object, and redraw */
  54.     WORD    obj;            /* it immediately.        */
  55.     {
  56.     WORD    state, newstate;
  57.     GRECT    root, ob_rect;
  58.  
  59.     objc_xywh(tree, ROOT, &root);
  60.     state = LWGET(OB_STATE(obj));
  61.     newstate = state ^ SELECTED;
  62.     objc_change(tree, obj, 0, root.g_x, root.g_y, 
  63.         root.g_w, root.g_h, newstate, 1);
  64.     }
  65.  
  66. .bp
  67. VOID                    /* If the object is not already */
  68. objc_sel(tree, obj)            /* SELECTED, make it so.    */
  69.     LONG    tree;
  70.     WORD    obj;
  71.     {
  72.     if ( !(LWGET(OB_STATE(obj)) & SELECTED) )
  73.         objc_toggle(tree, obj);
  74.     }
  75.  
  76.     VOID                /* If the object is SELECTED,    */
  77. objc_dsel(tree, obj)            /* deselect it.            */
  78.     LONG    tree;
  79.     WORD    obj;
  80.     {
  81.     if (LWGET(OB_STATE(obj)) & SELECTED)
  82.         objc_toggle(tree, obj);
  83.     }
  84.  
  85.     VOID                /* Return the object's GRECT      */
  86. objc_xywh(tree, obj, p)            /* through 'p'            */
  87.     LONG    tree;
  88.     WORD    obj;
  89.     GRECT    *p;
  90.     {
  91.     objc_offset(tree, obj, &p->g_x, &p->g_y);
  92.     p->g_w = LWGET(OB_WIDTH(obj));
  93.     p->g_h = LWGET(OB_HEIGHT(obj));
  94.     }
  95. .bp
  96.     VOID                /* Non-cursive traverse of an    */
  97. map_tree(tree, this, last, routine)    /* object tree.  This routine    */
  98.     LONG        tree;        /* is described in PRO GEM #5.    */
  99.     WORD        this, last;
  100.     WORD        (*routine)();
  101.     {
  102.     WORD        tmp1;
  103.  
  104.     tmp1 = this;        /* Initialize to impossible value: */
  105.                 /* TAIL won't point to self!       */
  106.                 /* Look until final node, or off   */
  107.                 /* the end of tree           */ 
  108.     while (this != last && this != NIL)
  109.                 /* Did we 'pop' into this node       */
  110.                 /* for the second time?           */
  111.         if (LWGET(OB_TAIL(this)) != tmp1)
  112.             {
  113.             tmp1 = this;    /* This is a new node       */
  114.             this = NIL;
  115.                     /* Apply operation, testing  */
  116.                     /* for rejection of sub-tree */
  117.             if ((*routine)(tree, tmp1))
  118.                 this = LWGET(OB_HEAD(tmp1));
  119.                     /* Subtree path not taken,   */
  120.                     /* so traverse right         */    
  121.             if (this == NIL)
  122.                 this = LWGET(OB_NEXT(tmp1));
  123.             }
  124.         else            /* Revisiting parent:          */
  125.                     /* No operation, move right  */
  126.             {
  127.             tmp1 = this;
  128.             this = LWGET(OB_NEXT(tmp1));
  129.             }
  130.     }
  131. .bp
  132.     WORD                /* Find the parent object of     */
  133. get_parent(tree, obj)            /* by traversing right until    */
  134.     LONG        tree;        /* we find nodes whose NEXT    */
  135.     WORD        obj;        /* and TAIL links point to     */
  136.     {                /* each other.            */
  137.     WORD        pobj;
  138.  
  139.     if (obj == NIL)
  140.         return (NIL);
  141.     pobj = LWGET(OB_NEXT(obj));
  142.     if (pobj != NIL)
  143.     {
  144.       while( LWGET(OB_TAIL(pobj)) != obj ) 
  145.       {
  146.         obj = pobj;
  147.         pobj = LWGET(OB_NEXT(obj));
  148.       }
  149.     }
  150.     return(pobj);
  151.     } 
  152.  
  153.     WORD
  154. inside(x, y, pt)        /* determine if x,y is in rectangle    */
  155.     WORD        x, y;
  156.     GRECT        *pt;
  157.     {
  158.     if ( (x >= pt->g_x) && (y >= pt->g_y) &&
  159.         (x < pt->g_x + pt->g_w) && (y < pt->g_y + pt->g_h) )
  160.         return(TRUE);
  161.     else
  162.         return(FALSE);
  163.     } 
  164.  
  165.     WORD
  166. rc_intersect(p1, p2)        /* compute intersection of two GRECTs    */
  167.     GRECT        *p1, *p2;
  168.     {
  169.     WORD        tx, ty, tw, th;
  170.  
  171.     tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
  172.     th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
  173.     tx = max(p2->g_x, p1->g_x);
  174.     ty = max(p2->g_y, p1->g_y);
  175.     p2->g_x = tx;
  176.     p2->g_y = ty;
  177.     p2->g_w = tw - tx;
  178.     p2->g_h = th - ty;
  179.     return( (tw > tx) && (th > ty) );
  180.     }
  181. .bp
  182.     VOID
  183. rc_copy(psbox, pdbox)        /* copy source to destination rectangle    */
  184.     GRECT    *psbox;
  185.     GRECT    *pdbox;
  186.     {
  187.     pdbox->g_x = psbox->g_x;
  188.     pdbox->g_y = psbox->g_y;
  189.     pdbox->g_w = psbox->g_w;
  190.     pdbox->g_h = psbox->g_h;
  191.     }
  192.  
  193. /************* "Hot-spot" manager and subroutines  ***************/
  194.  
  195.     WORD
  196. break_x(pxy)
  197.     WORD    *pxy;
  198.     {                /* Breaking object is right of    */
  199.     if (br_mx < pxy[0])        /* mouse.  Reduce width of     */
  200.         {            /* bounding rectangle.        */
  201.         br_rect.g_w = pxy[0] - br_rect.g_x;
  202.         return (TRUE);
  203.         }
  204.     if (br_mx > pxy[2])        /* Object to left.  Reduce width*/
  205.         {            /* and move rect. to right    */
  206.         br_rect.g_w += br_rect.g_x - pxy[2] - 1;
  207.         br_rect.g_x = pxy[2] + 1;
  208.         return (TRUE);
  209.         }
  210.     return (FALSE);            /* Mouse within object segment.    */
  211.     }                /* Break attempt fails.        */
  212. .bp
  213.     WORD
  214. break_y(pxy)
  215.     WORD    *pxy;
  216.     {
  217.     if (br_my < pxy[1])        /* Object below mouse.  Reduce    */
  218.         {            /* height of bounding rect.    */
  219.         br_rect.g_h = pxy[1] - br_rect.g_y;
  220.         return (TRUE);
  221.         }
  222.     if (br_my > pxy[3])        /* Object above mouse.  Reduce    */
  223.         {            /* height and shift downward.    */
  224.         br_rect.g_h += br_rect.g_y - pxy[3] - 1;
  225.         br_rect.g_y = pxy[3] + 1;
  226.         return (TRUE); 
  227.         }
  228.     /* Emergency escape test! Protection vs. turkeys who nest */
  229.     /* non-selectable objects inside of selectables.          */
  230.     if (br_mx >= pxy[0] && br_mx <= pxy[1])
  231.         {                /* Will X break fail?      */
  232.         br_rect.g_x = br_mx;        /* If so, punt!          */
  233.         br_rect.g_y = br_my;
  234.         br_rect.g_w = br_rect.g_h = 1;
  235.         return (TRUE);
  236.         }
  237.     return (FALSE);
  238.     }
  239. .bp
  240.     WORD
  241. break_obj(tree, obj)            /* Called once per object to    */
  242.     LONG    tree;            /* check if the bounding rect.    */
  243.     WORD    obj;            /* needs to be modified.    */
  244.     {
  245.     GRECT    s;
  246.     WORD    flags, broken, pxy[4];
  247.  
  248.     objc_xywh(tree, obj, &s);
  249.     grect_to_array(&s, pxy);
  250.     if (!rc_intersect(&br_rect, &s))
  251.         return (FALSE);        /* Trivial rejection case     */
  252.  
  253.     flags = LWGET(OB_FLAGS(obj));    /* Is this object a potential    */
  254.     if (flags & HIDETREE)        /* hot-spot?                 */
  255.         return (FALSE);
  256.     if ( !(flags & SELECTABLE) )
  257.         return (TRUE);
  258.     if (LWGET(OB_STATE(obj)) & DISABLED)
  259.         return (TRUE);
  260.  
  261.     for (broken = FALSE; !broken; ) /* This could take two passes     */
  262.         {            /* if the first break fails.       */
  263.         if (br_togl)
  264.             broken = break_x(pxy);
  265.         else
  266.             broken = break_y(pxy);
  267.         br_togl = !br_togl;
  268.         }
  269.     return (TRUE);
  270.     }
  271. .bp
  272.     WORD                /* Manages mouse rectangle events */
  273. form_hot(tree, hot_obj, mx, my, rect, mode)
  274.     LONG    tree;
  275.     WORD    hot_obj, mx, my, *mode;
  276.     GRECT    *rect;
  277.     {
  278.     GRECT    root;
  279.     WORD    state;
  280.  
  281.     objc_xywh(tree, ROOT, &root);    /* If there is already a hot-spot */
  282.     if (hot_obj != NIL)        /* turn it off.              */
  283.         objc_toggle(tree, hot_obj);
  284.  
  285.     if (!(inside(mx, my, &root)) )    /* Mouse has moved outside of       */
  286.         {            /* the dialog.  Wait for return.  */
  287.         *mode = M1_ENTER;
  288.         rc_copy(&root, rect);
  289.         return (NIL);
  290.         }
  291.                     /* What object is mouse over?      */
  292.                     /* (Hit is guaranteed.)           */
  293.     hot_obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
  294.                     /* Is this object a hot-spot?      */
  295.     state = LWGET(OB_STATE(hot_obj));
  296.     if (LWGET(OB_FLAGS(hot_obj)) & SELECTABLE)
  297.     if ( !(state & DISABLED) )
  298.         {            /* Yes!  Set up wait state.      */
  299.         *mode = M1_EXIT;
  300.         objc_xywh(tree, hot_obj, rect);
  301.         if (state & SELECTED)    /* But only toggle if it's not      */
  302.             return (NIL);    /* already SELECTED!          */
  303.         else
  304.             {
  305.             objc_toggle(tree, hot_obj);
  306.             return (hot_obj);
  307.             }
  308.         }
  309.  
  310.     rc_copy(&root, &br_rect);    /* No hot object, so compute    */
  311.     br_mx = mx;            /* mouse bounding rectangle.    */
  312.     br_my = my;
  313.     br_togl = 0;
  314.     map_tree(tree, ROOT, NIL, break_obj);
  315.     rc_copy(&br_rect, rect);    /* Then return to wait state.    */
  316.     *mode = M1_EXIT;
  317.     return (NIL);
  318.     }
  319. .bp
  320. /************* Key